Skip to content

Conversation

@amatsuda
Copy link
Member

@amatsuda amatsuda commented Feb 2, 2026

which allows users to customize how completion candidates are filtered.

Problem it solves

Currently, Reline hardcodes prefix matching for completion filtering - candidates must start with the typed text. And that behavior cannot be changed even by specifying completion_proc. This patch makes the filtering logic configurable, enabling alternative matching strategies like fuzzy matching (where "fb" can match "foo_bar").

Default behavior

When no custom proc is set, it falls back to the current prefix matching (respecting completion_ignore_case) for backward compatibility.

Example usage for fuzzy matching

Reline.completion_filter_proc = ->(target, candidate) {
  idx = 0
  target.each_char.all? { |c| (idx = candidate.index(c, idx)) && (idx += 1) }
}

This checks if each character in target appears in candidate in order (but not necessarily contiguously), enabling peco/fzf-style fuzzy matching.

To actually play with this example feature, for instance put something like this in the command line

ruby -Ilib -rreline -e "Reline.autocompletion = true; Reline.completion_proc = ->(_) { String.instance_methods(false).sort.map(&:to_s) }; Reline.completion_filter_proc = ->(target, candidate) { idx = 0; target.each_char.all? { |c| (idx = candidate.index(c, idx)) && (idx += 1) } }; puts Reline.readline('> ')"

and you can get "each_grapheme_cluster" by typing "egc". Enjoy!

which allows users to customize how completion candidates are filtered.

Problem it solves:
Currently, Reline hardcodes prefix matching for completion filtering -
candidates must start with the typed text. This patch makes the
filtering logic configurable, enabling alternative matching strategies
like fuzzy matching (where "fb" can match "foo_bar").

Default behavior:
When no custom proc is set, it falls back to prefix matching
(respecting completion_ignore_case) for backward compatibility.

Example usage for fuzzy matching:
Reline.completion_filter_proc = ->(target, candidate) {
  idx = 0
  target.each_char.all? { |c| (idx = candidate.index(c, idx)) && (idx += 1) }
}

This checks if each character in target appears in candidate in order
(but not necessarily contiguously), enabling peco/fzf-style fuzzy matching.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant